package com.hmall.order.web;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hmall.client.ItemClient;
import com.hmall.client.UserClient;
import com.hmall.common.pojo.Address;
import com.hmall.common.pojo.Item;
import com.hmall.common.pojo.User;
import com.hmall.order.constans.OrderMqConstants;
import com.hmall.order.holder.UserIdHolder;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.pojo.OrderRequest;
import com.hmall.order.service.IOrderDetailService;
import com.hmall.order.service.IOrderLogisticsService;
import com.hmall.order.service.IOrderService;
import com.hmall.order.utils.SnowflakeIdWorker;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private IOrderLogisticsService orderLogisticsService;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostMapping(value = "", name = "提交订单")
    @GlobalTransactional
    public ResponseEntity<Long> createOrder(@RequestBody OrderRequest orderRequest) {
        // 1.将Order写入数据库tb_order表中
        Order order = new Order();
        // 雪花算法生成orderId
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
        long orderId = idWorker.nextId();
        order.setId(orderId);
        // 根据地址id查询用户地址【远程调用userService】
        Address address = userClient.findAddressById(orderRequest.getAddressId());
        order.setUserId(address.getUserId());
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setPaymentType(orderRequest.getPaymentType());
        // 计算总费用  itemId  num 【远程调用itemService 查询item单价】
        Item item = itemClient.queryItemById(orderRequest.getItemId());
        order.setTotalFee(orderRequest.getNum() * item.getPrice());
        order.setStatus(1); // 未付款
        // 保存订单
        orderService.save(order);

        // 2.将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表 主要记录下单商品信息
        // 2.1保存订单详情
        OrderDetail orderDetail = new OrderDetail(orderRequest, item);
        orderDetail.setOrderId(orderId);
        orderDetailService.save(orderDetail);
        // 2.2 调用itemService的减库存 【远程调用itemService 更新库存】
        item.setStock(item.getStock() - orderRequest.getNum());
        itemClient.updateItem(item);

        // 3.将用户地址封装为OrderLogistics对象，写入tb_order_logistics表 主要记录下单地址
        OrderLogistics orderLogistics = new OrderLogistics(address);
        orderLogistics.setOrderId(orderId);
        orderLogisticsService.save(orderLogistics);

        // 5.发送延时订单消息   1800000 30分钟
        Message message = MessageBuilder
                .withBody((orderId + "").getBytes(StandardCharsets.UTF_8))
                .setHeader("x-delay", 600000)
                .build();
        // 消息Id
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        // 发送延时消息
        rabbitTemplate.convertAndSend(OrderMqConstants.EXCHANGE_NAME,
                OrderMqConstants.DELAY_KEY, message, correlationData);
        System.err.println("发送延时订单消息完成~~~");

        // 4. 返回订单id
        return ResponseEntity.ok(orderId);
    }

    /*前端页面自动调用*/
    @GetMapping("{id}")
    public Order queryOrderById(@PathVariable("id") Long orderId) {
        return orderService.getById(orderId);
    }

    @PostMapping("pay")
    @GlobalTransactional
    public ResponseEntity orderPay(@RequestBody Map map) {
        // 订单处理 【需要做幂等性判断】 可以在redis中存储orderId的key 支付前进行判断

        String payPassword = map.get("payPassword").toString();
        //String totalFee = map.get("totalFee").toString();
        String orderId = map.get("orderId").toString();
        Order order = orderService.getById(orderId);
        String trimPwd = payPassword.trim();
        // 查询用户支付密码  如果正确 减去 支付金额
        //Long userId = UserIdHolder.getUserId();
        // 远程调用根据id查询用户
        Long userId = order.getUserId();
        User user = userClient.queryUserById(userId);
        Long balance = user.getBalance() - order.getTotalFee();

        Boolean flag = false;

        try {
            if (trimPwd.equals(user.getPassword())) {
                // 减去金额
                Map map2 = new HashMap();
                map2.put("userId", userId);
                map2.put("balance", balance);
                // 远程调用更新 减去金额 成功 为 true ,失败 false
                flag = userClient.updateBalance(map2);
            }
        } catch (Exception e) {
            e.printStackTrace();
            ResponseEntity.ok(false);
        }

        return ResponseEntity.ok(flag);
    }

    /*处理延时订单消息*/
    public void handleOrder(Long orderId) {
        // 处理延时订单消息 【需要做幂等性判断】 可以在redis中存储orderId的key 支付前进行判断

        // 判断status是否已经支付  tb_order
        // 1. 如果status = 1 ,status修改为5 未支付 超时未支付订单，取消订单  修改库存量
        // 2. 如果是已支付，则不做处理
        Order order = orderService.getById(orderId);
        System.out.println("order.getStatus = " + order.getStatus());
        if (order.getStatus() == 1) {
            // 状态改为5
            order.setStatus(5);
            orderService.updateById(order);
            // tb_order_detail表 查询num
            QueryWrapper<OrderDetail> qw = new QueryWrapper<>();
            OrderDetail od = new OrderDetail();
            od.setOrderId(orderId);
            qw.setEntity(od);
            OrderDetail orderDetail = orderDetailService.getOne(qw);
            // 改回stock ==> 库存 + num
            Item item = itemClient.queryItemById(orderDetail.getItemId());
            item.setStock(item.getStock() + orderDetail.getNum());
            itemClient.updateItem(item);
        }
    }


}
